﻿using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace ZyGame
{
    [Serializable]
    public class AddressOptions
    {
        [SerializeField] [Header("服务器地址")] public List<AddressData> addressDatas;
    }

    [Serializable]
    public class AddressData
    {
        [Header("是否启用")] public bool isOn;
        [Header("别称")] public string name;
        [Header("地址")] public string address;
    }

    [Serializable]
    public class VFSOptions
    {
        /// <summary>
        /// 是否启用加解密
        /// </summary>
        [Header("是否启用加解密")] public bool isCrypt = true;

        /// <summary>
        /// AES 解密Key
        /// </summary>
        [Header("解密Key")] public string SecretId = string.Empty;

        /// <summary>
        /// AES解密密匙
        /// </summary>
        [Header("解密密匙")] public string SecretKey = string.Empty;

        /// <summary>
        /// 是否启用解压缩
        /// </summary>
        [Header("是否启用解压缩")] public bool isCompress = true;

        /// <summary>
        /// 文件IO缓存时间(秒)
        /// </summary>
        [Header("文件IO缓存时间(秒)")] public float IOCacheTime = 60;

        /// <summary>
        /// 资源缓存时间(秒)
        /// </summary>
        [Header("资源缓存时间(秒)")] public float AssetCacheTime = 60;

        /// <summary>
        /// 是否使用虚拟文件系统
        /// </summary>
        [Header("是否使用虚拟文件系统")] public bool isUseVFS = true;

        /// <summary>
        /// 虚拟文件系统文件数量
        /// </summary>
        [Header("虚拟文件系统文件数量")] public int VFSFileCount = 20;

        /// <summary>
        /// 虚拟文件系统单个文件大小
        /// </summary>
        [Header("虚拟文件系统单个文件大小")] public int VFSSingleFileSize = 1024 * 1024 * 2;

        /// <summary>
        /// 是否启用资源版本控制
        /// </summary>
        [Header("是否启用资源版本控制")] public bool useVersionControl = false;

        /// <summary>
        /// 文件扩展
        /// </summary>
        [Header("文件扩展")] public string packageExt = ".data";
    }

    [Serializable]
    public class HotfixOptions
    {
        /// <summary>
        /// 是否在编辑器模式下使用热更
        /// </summary>
        [Header("是否在编辑器模式下使用热更")] public bool UseHotfix = false;

        /// <summary>
        /// 是否启用脚本更新
        /// </summary>
        [Header("是否启用脚本更新")] public bool UseScriptHotfix = false;

        /// <summary>
        /// 是否启用资源更新
        /// </summary>
        [Header("是否启用资源热更")] public bool UseAssetHotfix = false;

        /// <summary>
        /// 热更dll
        /// </summary>
        [Header("热更逻辑DLL")] public string dllName;

        /// <summary>
        /// 补元数据dll
        /// </summary>
        [Header("HybridCLR 补元DLL列表")] public List<string> aotList;


        [SerializeField] [Header("热更资源地址")] public List<AddressData> AssetsUrl;
    }

    [Serializable]
    public class GameOptions
    {
        /// <summary>
        /// 屏幕分辨率
        /// </summary>
        [Header("屏幕分辨率")] public Vector2 screneSize = new Vector2(1920, 1080);

        /// <summary>
        /// 帧率
        /// </summary>
        [Header("帧率")] public int frameCount = 30;

        /// <summary>
        /// 存储桶名称
        /// </summary>
        [Header("资源桶")] public string bucket_name;

        /// <summary>
        /// 主包名
        /// </summary>
        [Header("主包名")] public string mainPackageName;

        /// <summary>
        /// 包列表根节点
        /// </summary>
        [Header("资源包搜索根节点")] public string packageRoot;

        /// <summary>
        /// 是否开启日志输出
        /// </summary>
        [Header("是否开启日志输出")] public bool CanWriteLogger = true;
    }

    [PathOptions("ProjectSettings/AppConfig.asset", PathOptions.Localtion.Internal)]
    public class AppConfig : Config<AppConfig>
    {
        [Header("游戏设置")] public GameOptions gameOptions;

        [Header("虚拟文件系统设置")] public VFSOptions vfsOptions;

        [Header("服务器地址设置")] public AddressOptions addressOptions;

        [Header("热更新设置")] public HotfixOptions hotfixOptions;


        public static string GetFileName(string name)
        {
            return $"{name}{instance.vfsOptions.packageExt}";
        }

        public static string GetServiceAddress(string name)
        {
            AddressData addressData = instance.addressOptions.addressDatas.Find(x => x.name == name && x.isOn);
            if (addressData is null)
            {
                throw new Exception($"没有找到[{name}],或是没有启用！");
            }

            return addressData.address;
        }

        public static string GetModuleFileListName(UnityEngine.Object target)
        {
            return GetFileName($"{target.name}_files");
        }

        public static string GetModuleFileListName(string module)
        {
            return GetFileName($"{module}_files");
        }

        public static string GetHotfixAssetPath(string fileName)
        {
            AddressData address = instance.hotfixOptions.AssetsUrl.Find(x => x.isOn);
            if (address is null)
            {
                throw new NullReferenceException("没有找到已经启用的资源地址");
            }

            return $"{address.address}/{GetPlatformName().ToLower()}/{fileName}";
        }

        public static string GetLocalFilePath(string fileName)
        {
            string dir = $"{Application.persistentDataPath}/{instance.gameOptions.bucket_name}/{GetPlatformName().ToLower()}";
            if (System.IO.Directory.Exists(dir) is false)
            {
                System.IO.Directory.CreateDirectory(dir);
            }

            return $"{dir}/{GetFileName(fileName.GetMd5())}";
        }

        public static string GetPlatformName()
        {
#if UNITY_ANDROID
            return "Android";
#elif UNITY_IPHONE
            return "IOS";
#elif UNITY_WEBGL
            return "WebGL";
#else
            return "Window";
#endif
        }

        public static byte[] GetCryptKey()
        {
            return Convert.FromBase64String(instance.vfsOptions.SecretId);
        }

        public static byte[] GetCryptIV()
        {
            return Convert.FromBase64String(instance.vfsOptions.SecretKey);
        }

        public static bool HasUseAssetsHotfix()
        {
#if UNITY_EDITOR
            return instance.hotfixOptions.UseHotfix && instance.hotfixOptions.UseAssetHotfix;
#else
            return true;
#endif
        }

        public static bool HasUseScriptsHotfix()
        {
#if UNITY_EDITOR
            return instance.hotfixOptions.UseHotfix && instance.hotfixOptions.UseScriptHotfix;
#else
            return true;
#endif
        }

        public static float GetAssetCacheTime()
        {
            return instance.vfsOptions.AssetCacheTime;
        }
    }
}